﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GA.Server.Api;
using GA.Server.Configuration;
using System.Security.Cryptography;

namespace GA.Server.GameApiManager
{
    public class GameApiManagerServer : GAServer
    {
        public override string Name
        {
            get { return typeof(GameApiManagerServer).Name; }
        }

        public GameApiManagerServer()
        {
        }

        public GameApiManagerServer(ServerPropertiesElementCollection properties)
            : base(properties)
        {
            if (properties == null) throw new ArgumentNullException("properties");
            if (properties.Get("ClientId") == null || properties.Get("ClientId").Value.Length == 0) throw new InvalidOperationException("properties must contain a client id.");
            if (properties.Get("AuthorizationCode") == null || properties.Get("AuthorizationCode").Value.Length == 0) throw new InvalidOperationException("properties must contain an authorization code.");

            mAuthorizationCode = properties.Get("AuthorizationCode").Value;
            mClientId = int.Parse(properties.Get("ClientId").Value);
            mMaximumSessionTime = TimeSpan.FromMinutes(10);
            mSessionSpawnTime = DateTime.MinValue;
            if (properties.Get("MaximumSessionTime") != null)
            {
                mMaximumSessionTime = TimeSpan.FromMinutes(double.Parse(properties.Get("MaximumSessionTime").Value));
            }
        }

        /// <summary>
        /// Gets a specific SignedApiCall.
        /// </summary>
        /// <typeparam name="T">SignedApiCall type to get.</typeparam>
        /// <returns>Constructed SignedApiCall.</returns>
        public T GetApiCall<T>() where T : SignedApiCall
        {
            if (DateTime.Now.Subtract(mSessionSpawnTime) > mMaximumSessionTime)
            {
                SpawnNewSession();
            }
            return (T)typeof(T).GetConstructor(new Type[] { typeof(int), typeof(string), typeof(string) }).Invoke(new object[] { mClientId, mAuthorizationCode, mSession.SessionId });
        }

        private void SpawnNewSession()
        {
            lock (mLockObject)
            {
                if (DateTime.Now.Subtract(mSessionSpawnTime) <= mMaximumSessionTime)
                {
                    return;
                }
                ApiInfoSession newSession = new ApiInfoSession(mClientId, mAuthorizationCode);
                newSession.LoadApi();
                mSession = newSession;
                mSessionSpawnTime = DateTime.Now;
            }
        }

        private DateTime mSessionSpawnTime;
        private TimeSpan mMaximumSessionTime;
        private ApiInfoSession mSession;
        private string mAuthorizationCode;
        private int mClientId;
        private object mLockObject = 0.984;
    }
}
